package T;

import T.Box;
import org.junit.Test;

import java.util.Date;

/**
 * @author zhiqi.shao
 * @Date 2018/5/31 10:10
 */
public class TestBox {


    /**
     * 使用我们的泛型类
     */
    @Test
    public void testBox_1(){
        Box<String> box=new Box<>("StringBox");
        //Box<String> box=new Box("StringBox");
        //Box<String> box=new Box<String>("StringBox");
        //上面的三种定义方式都可以
        System.out.println("box is:"+box.getData());
    }

    /**
     * 传入不同的泛型类型，判断是否是相同的实例类型
     * 答案是true
     * 总结：泛型只是适用在编译期的类型检查，编译后会擦除泛型的标记；
     * 也就是说，成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
     * 泛型类型在逻辑上看以看成是多个不同的类型，实际上都是相同的基本类型。
     */
    @Test
    public void testBox_2(){
        Box<String> box1=new Box<>("StringBox");
        //Box<double> box2=new Box<>(123.1);//Type argument cannot be of primitive type,所以原始类型不能用作泛型参数
        Box<Double> box2=new Box<>(123D);
        System.out.println(box1.getClass()==box2.getClass()?true:false);
    }

    /**
     * 我们的对象都是box,只是我们对象里的引用的泛型是我们传入的参数类型
     * 结果是：class java.lang.String:class java.lang.Double
     */
    @Test
    public void testBox_2_1(){
        Box<String> box1=new Box<>("StringBox");
        //Box<double> box2=new Box<>(123.1);//Type argument cannot be of primitive type,所以原始类型不能用作泛型参数
        Box<Double> box2=new Box<>(123D);
        System.out.println(box1.getData().getClass() +":"+  (box2.getData().getClass()));
    }


    /**
     *虽然：public final class Integer extends Number im,Integer 是Number的子类，
     *但是Box<Number> 不是Box<Integer>，如果是那是哪个类型？ 有违泛型设计的初衷
     */
    @Test
    public void testBox_3(){
        Box<Number> box1=new Box<Number>(88);
        /**
         * Required:Box<java.lang.Number>
         *         Found:Box<java.lang.Integer>
         */
        //Box<Number> box=new Box<>(88);//词句报错Incompatible types.
        Box<Integer> box2=new Box<>(98);

    }


    /**
     * 类型通配符一般是使用 ? 代替具体的类型实参。
     * box data:88:box data class:class T.Box
     * box data:98:box data class:class T.Box
     * box data:abc:box data class:class T.Box
     * box data:Thu May 31 11:10:05 CST 2018:box data class:class T.Box
     */
    @Test
    public void testBox_4(){
        Box<Number> box1=new Box<Number>(88);
        Box<Integer> box2=new Box<>(98);
        Box<String> box3 = new Box<>("abc");
        Box box=new Box(new Date());
        getDate(box1);
        getDate(box2);
        getDate(box3);
        getDate(box);
    }

    private void getDate(Box<?> box){
        System.out.println("box data:"+box.getData()+":box data class:"+box.getClass());
    }





}
